package com.cooksys.film_rental.dao.impl;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.cooksys.film_rental.dao.InventoryDao;
import com.cooksys.film_rental.model.Film;
import com.cooksys.film_rental.model.Inventory;
import com.cooksys.film_rental.model.Rental;
import com.cooksys.film_rental.model.Store;

@Repository("InventoryDao")
@Transactional
public class InventoryDaoImpl implements InventoryDao {

	@Autowired(required = true)
	private SessionFactory sessionFactory;

	/**
	 * 
	 * @return the current session from the internal {@link SessionFactory}
	 */
	public Session currentSession() {
		return sessionFactory.getCurrentSession();
	}

	@Override
	public Inventory getInventoryByInventoryId(Integer inventoryId) {
		Session session = currentSession();

		// returns a record from the INVENTORY table as an Inventory object
		// based on the given inventoryId, the table's primary key
		String hql = "from Inventory i where i.inventoryId = :inventoryId";

		Query query = session.createQuery(hql);
		query.setInteger("inventoryId", inventoryId);

		return (Inventory) query.list().get(0);

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Inventory> searchInventoriesByStore(Store store) {
		Session session = currentSession();

		// selects inventory objects associated with the given store
		String hql = "from Inventory i where i.store = :store";
		Query query = session.createQuery(hql);
		query.setEntity("store", store);

		return query.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Inventory> searchInventoriesByFilm(Film film) {
		Session session = currentSession();

		// selects inventory objects associated with the given film
		String hql = "from Inventory i where i.film = :film";
		Query query = session.createQuery(hql);
		query.setEntity("film", film);

		return query.list();
	}

	@Override
	public Inventory getInventoryByRental(Rental rental) {
		Session session = currentSession();

		// selects inventory objects associated with the given rental
		String hql = "select r.inventory from Rental r where r = :rental";
		Query query = session.createQuery(hql);
		query.setEntity("rental", rental);

		return (Inventory) query.list().get(0);
	}

	@Override
	public Inventory getInventoryByFilmAndStore(Film film, Store store) {
		Session session = currentSession();

		// selects inventory objects associated with the given film
		String hql = "from Inventory i where i.film = :film and i.store = :store and not exists ( select r.rentalId from Rental r where r.returnDate is null and r.inventory.inventoryId = i.inventoryId)";
		Query query = session.createQuery(hql);
		query.setEntity("film", film);
		query.setEntity("store", store);

		List results = query.list();
		if (results.size() == 0) {
			return null;
		}

		return (Inventory) results.get(0);
	}

}
